package com.gupao.javavip.netty.push.client.connection;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.apachecommons.CommonsLog;

import java.util.concurrent.TimeUnit;

@CommonsLog
public abstract class AbstractRetryConnector extends AbstractConnector implements RetryConnector {
    private int retries = 0;
    private long lastRetriesTime;

    private RetryStrategy retryStrategy;

    public AbstractRetryConnector(String host, int port) {
        this(host, port, new ExponentialBackOffRetry());
    }

    public AbstractRetryConnector(String host, int port, RetryStrategy retryStrategy) {
        super(host, port);

        this.retryStrategy = retryStrategy;
    }

    @Override
    public int getRetries() {
        return retries;
    }

    @Override
    protected void whenShutdown() {
    }

    @Override
    protected void afterConnect(ChannelFuture future) throws Exception {
        future.addListener(buildConnectionListener());
    }

    private ChannelFutureListener buildConnectionListener() {
        return future -> {
            if (!future.isSuccess()) {
                future.channel().pipeline().fireChannelInactive();
            } else {
                retries = 0;
            }
        };
    }

    @Override
    public void reConnect(ChannelHandlerContext ctx) {
        if (retryStrategy.allowRetry(retries)) {
            long sleepTimeMs = retryStrategy.getSleepTimeMs(retries);
            retries++;
            lastRetriesTime = System.currentTimeMillis();

            log.info("在" + sleepTimeMs + "毫秒之后，重试...");
            ctx.channel().eventLoop().schedule(() -> {
                log.info("第" + retries + "次重连 ...");
                connect();
            }, sleepTimeMs, TimeUnit.MILLISECONDS);
        } else {
            log.warn("重连失败超过最大次数，放弃重试...");
            log.info("最后重试的时间戳：" + lastRetriesTime);
        }
    }
}
